﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;

namespace CashCrusaderScript
{
    /// <summary>
    /// FastBitmap for pixel processing, source from C# kicks
    /// </summary>
    unsafe public class FastBitmap : IDisposable
    {
        private struct PixelData
        {
            public byte blue;
            public byte green;
            public byte red;
            public byte alpha;

            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Byte.ToString", Justification = "Byte.ToString() will not be change per Culture")]
            public override string ToString()
            {
                return "(" + alpha.ToString() + ", " + red.ToString() + ", " + green.ToString() + ", " + blue.ToString() + ")";
            }
        }

        private Bitmap workingBitmap = null;
        private int width = 0;
        private BitmapData bitmapData = null;
        private Byte* pBase = null;

        public int Width { get { return workingBitmap.Width; } }
        public int Height { get { return workingBitmap.Height; } }

        public FastBitmap(Bitmap inputBitmap)
        {
            workingBitmap = inputBitmap;
        }

        public void LockImage()
        {
            Rectangle bounds = new Rectangle(Point.Empty, workingBitmap.Size);

            width = (int)(bounds.Width * sizeof(PixelData));
            if (width % 4 != 0) width = 4 * (width / 4 + 1);

            //Lock Image
            bitmapData = workingBitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            pBase = (Byte*)bitmapData.Scan0.ToPointer();
        }

        private PixelData* _pixelData = null;

        public Color GetPixel(int x, int y)
        {
            _pixelData = (PixelData*)(pBase + y * width + x * sizeof(PixelData));
            return Color.FromArgb(_pixelData->alpha, _pixelData->red, _pixelData->green, _pixelData->blue);
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public Color GetPixelNext()
        {
            _pixelData++;
            return Color.FromArgb(_pixelData->alpha, _pixelData->red, _pixelData->green, _pixelData->blue);
        }

        public void SetPixel(int x, int y, Color color)
        {
            PixelData* pixels = (PixelData*)(pBase + y * width + x * sizeof(PixelData));
            pixels->alpha = color.A;
            pixels->red = color.R;
            pixels->green = color.G;
            pixels->blue = color.B;
        }

        public void UnlockImage()
        {
            workingBitmap.UnlockBits(bitmapData);
            bitmapData = null;
            pBase = null;
        }

        public FastBitmap Clone(Rectangle rect, PixelFormat pixelFormat)
        {
            return new FastBitmap(workingBitmap.Clone(rect, pixelFormat));
        }

        public Bitmap AsBitmap()
        {
            return workingBitmap;
        }

        private void DisposeMe()
        {
            workingBitmap.Dispose();            
        }

        public void Dispose()
        {
            DisposeMe();
            GC.SuppressFinalize(this);
        }

        ~FastBitmap()
        {
            DisposeMe();
        }
    }
}
